﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Configuration;
using System.IO;

namespace OSGeo.MapGuide
{
    /// <summary>
    /// A MapGuide base page that handles all the plumbing of:
    /// - Web Tier initialization
    /// - Session creation and maintenance
    /// - Service creation
    /// </summary>
    public class MgServerPage : Page
    {
        const string SESSION_KEY = "MG_SESSION_ID";

        protected override void OnInit(EventArgs e)
        {
            if (!this.IsPostBack)
            {
                InitializeWebTier();
            }
            MapGuideSetup(1);
            base.OnInit(e);
        }

        private void MapGuideSetup(int attempt)
        {
            if (attempt == 5)
                throw new ConfigurationException("Could not create a MapGuide session after " + attempt + " attempts");

            MgUserInformation userInfo = null;
            if (string.IsNullOrEmpty(this.MgSessionID))
            {
                //Try and get mg username password. On failure, default to Anonymous

                string user = ConfigurationManager.AppSettings["mgusername"];
                string pass = ConfigurationManager.AppSettings["mgpassword"];

                if (string.IsNullOrEmpty(user))
                {
                    user = this.DefaultUsername;
                    pass = this.DefaultPassword;
                }

                try
                {
                    userInfo = new MgUserInformation(user, pass);
                    MgSite site = new MgSite();
                    site.Open(userInfo);
                    this.MgSessionID = site.CreateSession();
                }
                catch (MgException)
                {
                    //If we can't create a session then this is probably something serious like MG server is offline. Don't bother retrying.
                    throw;
                }
            }

            //Now we have a valid session ID, create our site connection
            bool retry = false;
            try
            {
                userInfo = new MgUserInformation(this.MgSessionID);
                _conn = new MgSiteConnection();
                _conn.Open(userInfo);
            }
            catch (MgException ex)
            {
                ex.Dispose();
                retry = true;
                //Invalidate everything before retrying
                _conn = null;
                _drawingService = null;
                _featureService = null;
                _kmlService = null;
                _mappingService = null;
                _renderingService = null;
                _resourceService = null;
                _tileService = null;
            }

            if (retry)
            {
                MapGuideSetup(attempt++);
            }
        }

        /// <summary>
        /// Gets the default MapGuide username, when creating a new session
        /// </summary>
        public virtual string DefaultUsername
        {
            get { return "Anonymous"; }
        }

        /// <summary>
        /// Gets the default MapGuide password, when creating a new session
        /// </summary>
        public virtual string DefaultPassword
        {
            get { return string.Empty; }
        }

        private void InitializeWebTier()
        {
            string config = Server.MapPath("/mapguide/webconfig.ini");

            if (!File.Exists(config))
                config = ConfigurationManager.AppSettings["mgconfig"];
            
            if (!File.Exists(config))
                config = Server.MapPath("~/webconfig.ini");

            if (!File.Exists(config))
                throw new ConfigurationErrorsException(string.Format(Properties.Resources.ERR_WEBCONFIG_INI, Environment.NewLine));

            MapGuideApi.MgInitializeWebTier(config);
        }

        /// <summary>
        /// Gets the MapGuide Session ID
        /// </summary>
        public string MgSessionID
        {
            get
            {
                object obj = Session[SESSION_KEY];
                return (obj != null) ? (string)obj : string.Empty;
            }
            private set
            {
                Session[SESSION_KEY] = value;
            }
        }

        private MgSiteConnection _conn;

        private MgFeatureService _featureService;

        private MgResourceService _resourceService;

        private MgMappingService _mappingService;

        private MgRenderingService _renderingService;

        private MgKmlService _kmlService;

        private MgDrawingService _drawingService;

        private MgTileService _tileService;

        /// <summary>
        /// Gets the MapGuide Feature Service
        /// </summary>
        public MgFeatureService FeatureService
        {
            get
            {
                if (null == _featureService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _featureService = (MgFeatureService)_conn.CreateService(MgServiceType.FeatureService);
                }
                return _featureService;
            }
        }

        /// <summary>
        /// Gets the MapGuide Resource Service
        /// </summary>
        public MgResourceService ResourceService
        {
            get
            {
                if (null == _resourceService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _resourceService = (MgResourceService)_conn.CreateService(MgServiceType.ResourceService);
                }
                return _resourceService;
            }
        }

        /// <summary>
        /// Gets the MapGuide Mapping Service
        /// </summary>
        public MgMappingService MappingService
        {
            get
            {
                if (null == _mappingService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _mappingService = (MgMappingService)_conn.CreateService(MgServiceType.MappingService);
                }
                return _mappingService;
            }
        }

        /// <summary>
        /// Gets the MapGuide Rendering Service
        /// </summary>
        public MgRenderingService RenderingService
        {
            get
            {
                if (null == _renderingService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _renderingService = (MgRenderingService)_conn.CreateService(MgServiceType.RenderingService);
                }
                return _renderingService;
            }
        }

        /// <summary>
        /// Gets the MapGuide KML service
        /// </summary>
        public MgKmlService KmlService
        {
            get
            {
                if (null == _kmlService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _kmlService = (MgKmlService)_conn.CreateService(MgServiceType.KmlService);
                }
                return _kmlService;
            }
        }

        /// <summary>
        /// Gets the MapGuide Drawing Service
        /// </summary>
        public MgDrawingService DrawingService
        {
            get
            {
                if (null == _drawingService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _drawingService = (MgDrawingService)_conn.CreateService(MgServiceType.DrawingService);
                }
                return _drawingService;
            }
        }

        /// <summary>
        /// Gets the MapGuide Tile Service
        /// </summary>
        public MgTileService TileService
        {
            get
            {
                if (null == _tileService)
                {
                    if (null == _conn)
                    {
                        MapGuideSetup(1);
                    }
                    _tileService = (MgTileService)_conn.CreateService(MgServiceType.TileService);
                }
                return _tileService;
            }
        }
    }
}
